home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / packet / thenet / x1j4_src / tnl7a.c < prev    next >
Encoding:
Text File  |  1995-03-10  |  42.8 KB  |  1,297 lines

  1. /*****************************************************************************/
  2. /*                                              */
  3. /*                                         */
  4. /*    *****              *****                      */
  5. /*     *****            *****                         */
  6. /*       *****          *****                         */
  7. /*         *****        *****                         */
  8. /*  ***************      ***************                     */
  9. /*  *****************    *****************                     */
  10. /*  ***************      ***************                     */
  11. /*         *****        *****       TheNet                    */
  12. /*       *****          *****       Portable. Compatible.         */
  13. /*     *****            *****       Public Domain             */
  14. /*    *****              *****    NORD><LINK                  */
  15. /*                                         */
  16. /* This software is public domain ONLY for non commercial use                */
  17. /*                                                                           */
  18. /*                                         */
  19. /*****************************************************************************/
  20.  
  21. /* Level 7A, Dataswitch                                 */
  22. /* Version 1.01                                   */
  23. /* Hans Georg Giese, DF2AU, Hinter dem Berge 5, 3300 Braunschweig         */
  24. /* 05-MAY-88                                     */
  25.  
  26. /* Modified Dec 90 / Jan 91 by D Roberts                     */
  27. /*    Added DOS debug support ( #ifdef MSDOS ... )                 */
  28. /*    Corrected bug in seteom() where indirection error             */
  29. /*    Changed signon optionally on MODBYSTRING & SIGNONTEXT  definition    */
  30. /*    CQ command may be removed by defining NOCQ                 */
  31. /*    modify position of variables for bank switched version             */
  32. /*      Added register keyword to reduce code size                           */
  33. /*    Use all.h header file                                                */
  34. /*    Add additional command optionally on definition of STATSCMD          */
  35. /*      Add optionally on HOSTCMD another command - 'host'                   */
  36. /*      Make error message reflect permitted commands                        */
  37. /*      Add 'BYE' message optionally on MODIFIED                             */
  38. /*      Add 'bbs' command optionally on HOSTCMD                              */
  39. /*      Add 'mheard' command optionally on MONITORCMD                        */
  40. /*      Move beacon digilist to configuration area if MODIFIED defined       */
  41. /*      Add MODE command parameter table support                             */
  42. /*      Add TALK command optionally on TALKCMD definition                    */
  43. /*      Upgrade password checking conditionally on MODIFIED                  */
  44. /*      Add MANAGER and AUDIT commands optionally on MANAGED                 */
  45. /*      Add Links command optionally on LINKSCMD                             */
  46. /*      Make beacon timer configurable                                       */
  47. /*      Add configuration option to make 'connect' to to BBS or host         */
  48. /*      Add calibrate command optionally on CWID                             */
  49. /*      Conditionally exclude HI and LOW on definition of NOHILOW            */
  50. /*      Move order of commands so that LINKS precedes LOW                    */
  51. /*      Add DXcluster command optionally on DXCLUSTER if HOSTCMD enabled     */
  52. /*      Added Beacon text command optionally on MODIFIED                     */
  53. /*      Added closedown command optionally on CLOSEDOWN                      */
  54. /*      Add help messages control word for connect trying info message       */
  55. /*      Add ACL command and related stuff                                    */
  56. /*      Make all commands visible for sysop if help bit set                  */
  57. /*      Add connect text message on alias l2 connect                         */
  58. /*      Add help message                                                     */
  59. /*      Add ALIAS, BBSAlias, HostAlias & DXCluster commands on MODIFIED      */
  60. /*      Add QUIT as an alternative to Bye                                    */
  61. /*      Added iproute command optionally on IPROUTE                          */
  62. /*      remove unnecessary '== 1' and similar constructs                     */
  63. /*      reduce min L4 retries to 1                                           */
  64. /*      add MTU command                                                      */
  65. /*      add METER command to control ADC                                     */
  66. /*      change command interpreter to support 8 bit data option              */
  67. /*      add option for reconnection to node after remote disconnection       */
  68. /*                                                                           */
  69. /* September 1993 - released as TheNet X-1J                                  */
  70. /*                                                                           */
  71. /*      add optional support for TexNet on variable TEXNET                   */
  72. /*      add adc support ( mheard & adc command                               */
  73. /*      upgrade ccpmet & table to support meters                             */
  74.  
  75. #include "all.h"
  76. #include "tntyp.h"        /* Definition der Typen                 */
  77. #ifdef BANKED
  78. #define EXTERN extern
  79. #else
  80. #define EXTERN
  81. #endif
  82.  
  83. #include "tnl7av.h"
  84. #include "tnl7ae.h"        /* externe Definitionen                 */
  85.  
  86. /*---------------------------------------------------------------------------*/
  87. #ifdef BANKED
  88. extern char beades[];
  89. extern char cqdest[];
  90. extern char cqdil[];
  91. #else
  92. char    beades[] = { 'I','D',' ',' ',' ',' ','\140' }; /* Call fuer Bake     */
  93. char    cqdest[] = { 'C','Q',' ',' ',' ',' ','\140' }; /* Call fuer CQ-Ruf   */
  94. char    cqdil[]  = "";                    /* Digiliste fuer CQ-Ruf */
  95. #endif
  96. #ifndef MODIFIED
  97. char    beadil[] = "";                    /* Digiliste fuer Bake   */
  98. #else
  99. extern char beadil[];
  100. #endif
  101. char    dmmsg[]  = "Busy from ";            /* DM Meldung         */
  102. char    conmsg[] = "Connected to ";            /* Connect Meldung         */
  103. char    version[] = SIGNONTEXT;                /* Kopfmeldung         */
  104. /*---------------------------------------------------------------------------*/
  105. partyp    partab[] = {        /* Parameter Tabelle                 */
  106.     &maxdes,   1,    400,    /* maximale Laenge der Destination Liste     */
  107.     &worqua,   0,    255,    /* minimale Qualiatet fuer Autoupdate         */
  108.     &ch0qua,   0,    255,    /* HDLC Kanal Qualitaet                 */
  109.     &ch1qua,   0,    255,    /* RS232 Kanal Qualitaet             */
  110.     &obcini,   0,    255,    /* Anfangswert Knotenlebensdauer         */
  111.     &obcbro,   1,    255,    /* min Wert Restlebensdauer fuer Rundspruch  */
  112.     &broint,   0, 0xffff,    /* Rundspruchintervall                 */
  113.     &timliv,   0,    255,    /* Anfangswert Paketlebensdauer             */
  114.     &tratou,   5,    600,    /* Timeout in Level3                 */
  115.     &tratri,   1,    127,    /* Versuche in Level3                 */
  116.     &traack,   0,     60,    /* Level3 Wartezeit bis ACK             */
  117.     &trabsy,   1,   1000,    /* Level3 Busy Wartezeit             */
  118.     &trawir,   1,    127,    /* vorgeschlagene Fenstergroesse in Level3   */
  119.     &conctl,   1,    127,    /* gebufferte Frames je Verbindung         */
  120.     &ininat,   0, 0xffff,    /* no-activity-timeout                 */
  121.     &Ppar,     0,    255,    /* Entschlossenheit fuer Sendung frei        */
  122.     &Wpar,     0,    127,    /* Zeitschlitzbreite                 */
  123.     &Fpar,     1,     15,    /* Level2, Timer1                 */
  124.     &Opar,     1,      7,    /* Level2, Fenstergroesse             */
  125.     &Npar,     0,    127,    /* Level2, Versuche                 */
  126.     &T2par,    0,   6000,    /* Level2, Timer2                 */
  127.     &T3par,    0, 0xffff,    /* Level2, Timer3                 */
  128.     &Rpar,     0,      1,    /* Level2 Digipeating Freigabe             */
  129.     &VCpar,    0,      1,    /* Calls pruefen                 */
  130.     &beacen,   0,      2,    /* Bake ein-aus                     */
  131.     &cqen,     0,      1    /* CQ-Ruf ein-aus                 */
  132. };
  133.  
  134. #ifdef MODIFIED
  135. partyp modtab[] =
  136. {
  137.     &hstmod,  0,    1,    /* host mode, 0 = normal, 1 = rs232 ctrl */
  138.     &cwiden,  0,    3600,    /* cwid repeat period in seconds */
  139.     &cwspeed, 4,    10,    /* cwid tick period, in 10's of milliseconds*/
  140.     &brochn,  0,    MAXPORTMASK,    /* nodes bcast channel control */
  141.     &crlmod,  0,    3,    /* crosslink protocol mode setting */
  142.     &Tpar,    0,    255,    /* TXdelay */
  143.     &Dpar,    0,    1,    /* full duples control */
  144.     &br1int,  0,    0xffff,    /* port 1 nodes broadcast period / control */
  145.     &broalg,  0,    MAXPORTMASK,    /* node broadcast algorithm control */
  146.     &beaint,  600,  3600,    /* beacon interval timer */
  147.     &ctobbs,  0,    2,    /* connect to BBS if 1, DXC if 2, host otherwise*/
  148.     &hlpflg,  0,    255,    /* help messages control word */
  149.     &nohashnode, 0, MAXPORTMASK, /* no hash node b'cast port control */
  150.     &enaliases,0,   1,    /* enable extra aliases monitoring */
  151.     &reconnect,0,    1,    /* reconnect to node on remote disconnect */
  152.     &no_slime, 0,    3,    /* slime trail control word */
  153.     &no_digi,  0,   3    /* digi to / from node control word */
  154. };
  155. #endif
  156.  
  157. #ifdef MOD_MTU
  158. partyp mtutab[] =
  159. {
  160.     &mtu_ip0,    64,    1024,    /* ip mtu for radio port */
  161.     &mtu_ip1,    64,    1024,    /* ip mtu for rs232 port */
  162.     &mtu_ipn,    64-20,    256-20,    /* ip mtu for netrom port */
  163.     &mtu_i_max,    257,    1025,    /* max data in L2 I frame +1 */
  164.     &mtu_l2_max,    328,    1096    /* total max frame size @ L2 */
  165. };
  166. #endif
  167.  
  168. #ifdef METERS
  169. partyp mettab[] =
  170. {
  171. #ifdef ALL_METERS
  172.     &meterflags,    0,    0x7fff,        /* mode flags */
  173. #else
  174.     &meterflags,    0,    511,        /* mode flags */
  175. #endif
  176.     &rxdev,        0,    255,        /* receiver deviation */
  177.     &rxsigmin,    0,    255,        /* adc noise floor count */
  178.     &rxsmeter,    0,    255,        /* s meter multiplier */
  179.     &rxdb,        0,    255,        /* dB scale multipler */
  180.     &dbfloor,    0,    255,        /* dB noise floor */
  181.     &adcmult1,    0,    255,        /* voltage ( ch3 ) mult. */
  182.     &adcmult2,    0,    255,        /* voltage ( ch4 ) mult. */
  183.     &adcofs1,    0,    255,        /* voltage ( ch3 ) offset. */
  184.     &adcofs2,    0,    255        /* voltage ( ch4 ) offset. */
  185. #ifdef ALL_METERS
  186.     ,
  187.     &adcmult3,    0,    255,        /* voltage ( ch1 ) mult. */
  188.     &adcmult4,    0,    255,        /* voltage ( ch2 ) mult. */
  189.     &adcofs3,    0,    255,        /* voltage ( ch1 ) offset. */
  190.     &adcofs4,    0,    255        /* voltage ( ch2 ) offset. */
  191. #endif
  192. };
  193. #endif
  194.  
  195. #ifdef PK96
  196. partyp bratab[] =
  197. {
  198.     &brate0,    0,    6,
  199.     &brate1,    0,    6
  200. };
  201. #endif
  202.  
  203. /*---------------------------------------------------------------------------*/
  204. /* The audit command sets the value of the audit mask. Each bit corresponds
  205.  * to a type of auditing as shown below :
  206.  *           bit    use
  207.  *            0     level 1 auditing enable
  208.  *            1     level 2 auditing
  209.  *            2     reserved
  210.  *            3     level 4 auditing
  211.  *            4     level 7 data switch - use of sysop command
  212.  *            5     level 7 - all use commands ( overrides bit 4 )
  213.  *            6     CPU statistics auditing enable
  214.  *            7-15  reserved
  215.  */
  216.  
  217. #ifdef MANAGED
  218. partyp audtab[] =
  219. {
  220.     &auditmask,    0,    255
  221. };
  222. #endif
  223.  
  224. /*---------------------------------------------------------------------------*/
  225. cmdtyp    cmdtab[] = {        /* Befehlstabelle                 */
  226.         ccpcm1, ccpcon,
  227. #ifndef NOCQ
  228.     ccpcm8, ccpcq,
  229. #endif
  230. #ifdef    MODIFIED
  231.     ccpc14, ccpbye,
  232.     ccpc28, ccphlp,
  233. #endif
  234.     ccpcm2, ccpide,
  235.     ccpcm3, ccpnod,
  236.     ccpcm4, ccppar,
  237.     ccpcm9, ccprou,
  238. #ifdef  TALKCMD
  239.         ccpc18, ccpcht,
  240. #endif
  241. #ifdef    STATSCMD
  242.     ccpc12, ccpsts,
  243. #endif
  244. #ifdef    HOSTCMD
  245.     ccpc13, ccphst,
  246.     ccpc15, ccpbbs,
  247. #ifdef DXCLUSTER
  248.     ccpc23, ccpdxc,
  249. #endif
  250. #endif
  251. #ifdef MONITORCMD
  252.     ccpc16, ccpmh,
  253. #endif
  254. #ifdef MODIFIED
  255.     ccpc17, ccpmod,
  256. #endif
  257.     ccpcm5, ccpres,
  258.     ccpcm6, ccpsys,
  259.     ccpcm7, ccpuse,
  260. #ifdef LINKSCMD
  261.     ccpc21, ccplin,
  262. #endif
  263. #ifndef NOHILOW
  264.     ccpc10, ccphig,
  265.     ccpc11, ccplow,
  266. #endif
  267. #ifdef ACL
  268.     ccpc26, ccpacl,
  269. #endif
  270. #ifdef MANAGED
  271.     ccpc19, ccpman,
  272.     ccpc20, ccpaud,
  273. #endif
  274. #ifdef CWID
  275.     ccpc22, ccpcal,
  276. #endif
  277. #ifdef CLOSEDOWN
  278.     ccpc24, ccpclo,
  279. #endif
  280. #ifdef MODIFIED
  281.     ccpc25, ccpbtx,
  282.     ccpc27, ccpctx,
  283.     ccpc33, ccpali,
  284. #ifdef HOSTCMD
  285.     ccpc29, ccpbba,
  286.     ccpc31, ccphoa,
  287. #endif
  288. #ifdef DXCLUSTER
  289.     ccpc30, ccpdxa,
  290. #endif
  291.     ccpc32, ccpbye,
  292.     ccpc35, ccpui,
  293. #endif
  294. #ifdef IPROUTE
  295.     ccpc36, ccpipr,
  296.     ccpc37, ccparp,
  297.     ccpc38, ccpips,
  298.     ccpc39, ccpipa,
  299.     ccpc40, ccpipb,
  300. #endif
  301. #ifdef MOD_MTU
  302.     ccpc41, ccpmtu,
  303. #endif
  304. #ifdef METERS
  305.     ccpc42, ccpmet,
  306.     ccpc43, ccpadc,
  307.     ccpc44, ccpad1,
  308.     ccpc45, ccpad2,
  309. #ifdef ALL_METERS
  310.     ccpc49, ccpad3,
  311.     ccpc50, ccpad4,
  312. #endif
  313. #endif
  314. #ifdef PK96
  315.     ccpc46, ccpbra,
  316. #endif
  317. #ifdef L3MONITOR
  318.     ccpc47, ccpmh3,
  319. #endif
  320. #ifdef IPROUTE
  321.     ccpc48, ccpart,
  322. #endif
  323.     0, 0
  324. };
  325.  
  326. char    ccpcm1[] = "Connect";
  327. char    ccpcm8[] = "CQ";
  328. char    ccpcm2[] = "Info";
  329. char    ccpcm3[] = "Nodes";
  330. char    ccpcm4[] = "Parms";
  331. char    ccpcm9[] = "Routes";
  332. char    ccpcm5[] = "Reset";
  333. char    ccpcm6[] = "Sysop";
  334. char    ccpcm7[] = "Users";
  335. #ifndef NOHILOW
  336. char    ccpc10[] = "High";
  337. char    ccpc11[] = "Low";
  338. #endif
  339. #ifdef STATSCMD
  340. char    ccpc12[] = "Stats";
  341. #endif
  342. #ifdef HOSTCMD
  343. char    ccpc13[] = "Host";
  344. char    ccpc15[] = "BBS";
  345. #ifdef DXCLUSTER
  346. char    ccpc23[] = "DXcluster";
  347. #endif
  348. #endif
  349. #ifdef MODIFIED
  350. char    ccpc14[] = "Bye";
  351. char    ccpc32[] = "Quit";
  352. char    ccpc17[] = "Mode";
  353. char    ccpc28[] = "Help";
  354. #endif
  355. #ifdef MONITORCMD
  356. char    ccpc16[] = "MHeard";
  357. #endif
  358. #ifdef TALKCMD
  359. char    ccpc18[] = "Talk";
  360. #endif
  361. #ifdef MANAGED
  362. char    ccpc19[] = "Manager";
  363. char    ccpc20[] = "Audit";
  364. #endif
  365. #ifdef LINKSCMD
  366. char    ccpc21[] = "Links";
  367. #endif
  368. #ifdef CWID
  369. char    ccpc22[] = "Calibrate";
  370. #endif
  371. #ifdef CLOSEDOWN
  372. char    ccpc24[] = "Closedown";
  373. #endif
  374. #ifdef MODIFIED
  375. char    ccpc25[] = "Btext";
  376. char    ccpc27[] = "Ctext";
  377. char    ccpc33[] = "Alias";
  378. #ifdef HOSTCMD
  379. char    ccpc29[] = "BBSAlias";
  380. char    ccpc31[] = "HostAlias";
  381. #endif
  382. #ifdef DXCLUSTER
  383. char    ccpc30[] = "DXCAlias";
  384. #endif
  385. char    ccpc35[] = "UI";
  386. #endif
  387. #ifdef ACL
  388. char    ccpc26[] = "ACL";
  389. #endif
  390. #ifdef IPROUTE
  391. char    ccpc36[] = "IProute";
  392. char    ccpc37[] = "ARP";
  393. char    ccpc38[] = "IPstats";
  394. char    ccpc39[] = "IPaddress";
  395. char    ccpc40[] = "IPbroadcast";
  396. #endif
  397. #ifdef MOD_MTU
  398. char    ccpc41[] = "MTU";
  399. #endif
  400. #ifdef METERS
  401. char    ccpc42[] = "Meters";
  402. char    ccpc43[] = "Adc";
  403. char    ccpc44[] = "Adc1";
  404. char    ccpc45[] = "Adc2";
  405. #ifdef ALL_METERS
  406. char    ccpc49[] = "Adc3";
  407. char    ccpc50[] = "Adc4";
  408. #endif
  409. #endif
  410. #ifdef PK96
  411. char    ccpc46[] = "Brate";
  412. #endif
  413. #ifdef L3MONITOR
  414. char    ccpc47[] = "L3MHeard";
  415. #endif
  416. #ifdef IPROUTE
  417. char    ccpc48[] = "ARPtimer";
  418. #endif
  419.  
  420. /* the following table controls the display of commands and their use.
  421.  * value 0 = command enabled, will be displayed in 'help' screen
  422.  *       1 = command disabled, will display if enabled
  423.  *       2 = enabled but will never display in help screen ( sysop cmds )
  424.  * The order of these entries must match the order of the commands in the
  425.  * cmdtab[] structure.
  426.  */
  427.  
  428. #ifdef MODIFIED
  429. unsigned char defcst[] = 
  430. { 0,    /* connect */
  431. #ifndef NOCQ
  432.   0,    /* cq */
  433. #endif
  434.   0,    /* bye */
  435.   0,    /* help */
  436.   0,    /* ident */
  437.   0,    /* node */
  438.   2,    /* parms */
  439.   0,    /* route */
  440. #ifdef TALKCMD
  441.   0,    /* talk */
  442. #endif
  443. #ifdef STATSCMD
  444.   0,    /* stats */
  445. #endif
  446. #ifdef HOSTCMD
  447.   0,    /* host */
  448.   0,    /* bbs */
  449. #ifdef DXCLUSTER
  450.   0,    /* dxcluster */
  451. #endif
  452. #endif
  453. #ifdef MONITORCMD
  454.   0,    /* mheard */
  455. #endif
  456.   2,    /* mode */
  457.   2,    /* reset */
  458.   2,    /* sysop */
  459.   0    /* users */
  460. #ifdef LINKSCMD
  461.   ,2    /* links */
  462. #endif
  463. #ifndef NOHILOW
  464.   ,2    /* high */
  465.   ,2    /* low */
  466. #endif
  467. #ifdef ACL
  468.   ,2    /* acl */
  469. #endif
  470. #ifdef MANAGED
  471.   ,2    /* manager */
  472.   ,2    /* audit */
  473. #endif
  474. #ifdef CWID
  475.   ,2    /* calibrate */
  476. #endif
  477. #ifdef CLOSEDOWN
  478.   ,2    /* closedown */
  479. #endif
  480. #ifdef MODIFIED
  481.   ,2    /* btext */
  482.   ,2    /* ctext */
  483.   ,2    /* alias */
  484. #ifdef HOSTCMD
  485.   ,2    /* bbsalias */
  486.   ,2    /* hostalias */
  487. #endif
  488. #ifdef DXCLUSTER
  489.   ,2    /* dxcalias */
  490. #endif
  491.   ,0    /* Quit */
  492.   ,2    /* UI   */
  493. #endif
  494. #ifdef IPROUTE
  495.   ,0    /* iproute */
  496.   ,0    /* arp */
  497.   ,2    /* ipstats */
  498.   ,2    /* ipaddress */
  499.   ,2    /* ipbroadcast */
  500. #endif
  501. #ifdef MOD_MTU
  502.   ,2    /* mtu */
  503. #endif
  504. #ifdef METERS
  505.   ,2    /* meters */
  506.   ,0    /* adc */
  507.   ,2    /* adc1 */
  508.   ,2    /* adc2 */
  509. #ifdef ALL_METERS
  510.   ,2    /* adc3 */
  511.   ,2    /* adc4 */
  512. #endif
  513. #endif
  514. #ifdef PK96
  515.   ,2    /* brate */
  516. #endif
  517. #ifdef L3MONITOR
  518.   ,2    /* L3MHeard */
  519. #endif
  520. #ifdef IPROUTE
  521.   ,2    /* ARPtimer */
  522. #endif
  523. };
  524. #endif
  525.  
  526. /*---------------------------------------------------------------------------*/
  527. mainf() {            /* Einsprung vom Assembler Teil nach Init    */
  528.   DIinc();            /* Interrupts aus                 */
  529.   inivar();            /* Variable initialisieren             */
  530.   initmisc();
  531.   initl4();            /* Level 4      "                 */
  532.   l3init();            /* Level 3      "                 */
  533.   l2init();            /* Level 2      "                     */
  534. #ifdef IPROUTE
  535.   ipinit();            /* Initialise Internet gateway handler */
  536. #endif
  537.   hosini();            /* Hostinterface initialisieren             */
  538.   srand();            /* Zufallsgenerator initialisieren         */
  539.   decEI();            /* Interrupts wieder an                 */
  540.   bstrng("\015\012");
  541.   bstrng(version);        /* melden                     */
  542.   bcalou(myid);            /* eigenes Call                     */
  543. #ifdef MODIFIED
  544.   bstrng(MODBYSTRING);
  545. #else
  546.   bstrng(")\015\012by NORD><LINK (DF2AU/DC4OX)\015\012\012");
  547. #endif
  548.  
  549.   loop:                /* ewige Schleife                 */
  550.     hostsv();            /* Hostinterface                 */
  551.     l2();            /* Level 2                     */
  552.     l3serv();            /* Level 3                     */
  553. #ifdef IPROUTE
  554.     ipserv();            /* route all outstanding IP frames           */
  555. #endif
  556.     l4serv();            /* Level 4                     */
  557.     timsrv();            /* Timerservice                     */
  558. #ifdef MSDOS
  559.     inputdata();        /* poll for input data via DOS */
  560. #endif
  561.     goto loop;
  562. }
  563.  
  564. /*---------------------------------------------------------------------------*/
  565. VOID    inivar()        /* Variable initialisieren             */
  566.   {
  567.   register unsigned cnt;    /* Scratch Zaehler                 */
  568.   register char *chaptr;    /* fuer Passwort kopieren             */
  569.  
  570.   inithd(&usccpl);        /* CCP User Liste initialisieren         */
  571.   inithd(&userhd);        /* User Liste initialisieren             */
  572.  
  573.   for (cnt = 0, ptcrdp = ptcrdl;/* Patchcordliste aufbauen             */
  574.        cnt < NUMPAT; ++cnt, ++ptcrdp) {
  575.     ptcrdp->luserl = 0;        /* kein Kontrollblock                 */
  576.     }
  577.   tic10 =            /* loeschen: 10ms Timer                 */
  578.   lastic =            /* letzte Ablesung bei 0             */
  579.   tic1s =            /* Sekundenzaehler                 */
  580.   beatim = 0;            /* Bakenuhr                     */
  581.  
  582.   if (!iswarm()) {        /* nur im Kaltstart                 */
  583.     Ypar   = MAXL2L;        /* maximal Links in Level2             */
  584.     Tpar   = DEFTP;        /* Senderverzoegerung                 */
  585.     Ppar   = DEFPER;        /* Persistance                     */
  586.     Wpar   = DEFSLO;        /* Zeitscheibengroesse                 */
  587.     Fpar   = DEFRAK;        /* Level2 FRACK                     */
  588.     Opar   = DEFMAF;        /* Fenstergroesse in Level2             */
  589.     Npar   = DEFL2T;        /* Versuche in Level2                 */
  590.     T2par  = DEFLT2;        /* Level2 Timer 2                 */
  591.     T3par  = DEFLT3;        /* Level2 Timer 3                 */
  592.     Rpar   = DEFRPA;        /* Level2 Digipeating                 */
  593.     Vpar   = DEFL2L;        /* Level2 Protokollversion             */
  594.     Dpar   = DEFDPA;        /* Full-Duplex                     */
  595.     xFpar  = DEFXFP;        /* Full-Duplex mit Flags             */
  596.     ininat = DEFNOA;        /* no-activity-timeout                 */
  597.     conctl = DEFCON;        /* Frames im Buffer je Link             */
  598.     beacen = DEFBEA;        /* Bakenform                     */
  599. #ifdef HOSTMODE
  600.     hstmod = DEFHOS;        /* default host mode control */
  601. #endif
  602. #ifdef KISSMODE
  603.     crlmod = DEFKIS;        /* default crosslink ( KISS ) mode setting */
  604. #endif
  605. #ifdef HOSTCMD
  606.     bbsid[0] = hostid[0] = 
  607.     hidlen = bbslen = 0;    /* clear the BBS and HOST destinations */
  608. #ifdef MODIFIED
  609.     cpy6ch(bbsalias, nulide);    /* Ident setzen                     */
  610.     cpy6ch(hostalias, nulide);    /* Ident setzen                     */
  611. #endif
  612. #endif
  613. #ifdef DXCLUSTER
  614.     dxcid[0] =
  615.     dxclen = 0;                /* clear the dxcluster destination */
  616. #ifdef MODIFIED
  617.     cpy6ch(dxcalias, nulide);    /* Ident setzen                     */
  618. #endif
  619. #endif
  620. #ifdef MODIFIED
  621.     memcpy( defcsr, defcst, sizeof( defcst ) );
  622.     beaint = DEFBIN;        /* default beacon broadcast period */
  623.     ctobbs = DEFCSB;        /* default 'connect' to BBS or host */
  624.     *beatxt = '\0';            /* clear sysop beacon message */
  625.     hlpflg = DEFHLP;        /* help messages default word */
  626.     *contxt = '\0';        /* clear connect text message */
  627.     enaliases = 0;
  628.     nohashnode = DEFNOHASH;
  629. #ifdef ACL
  630.   inithd(&acl);            /* initialise access control list */
  631.   acl_mask = acl_default = 0;
  632. #endif
  633. #endif
  634.  
  635.     paswle = 0;            /* Passwort aus Eprom kopieren             */
  636.     chaptr = &DEFPWD[0];
  637.     while (*chaptr != 0)
  638.      {
  639.       paswrd[paswle++] = *chaptr++;
  640.      }
  641.  
  642.     infmsg[0] = 0;        /* keine Info-Message                 */
  643.     cpyid(myid, DEFCAL);    /* Call setzen                     */
  644.     cpy6ch(alias, DEFIDE);    /* Ident setzen                     */
  645.     VCpar  = DEFVAL;        /* Call pruefen                     */
  646.     cqen   = DEFCQ;             /* CQ flag initialisation                    */
  647.     reconnect = DEFRECONNECT;    /* initialise reconnect on disconnect flag   */
  648.     no_slime = DEFNO_SLIME;    /* initalise slime trail control word        */
  649.     no_digi = DEFNO_DIGI;    /* initialise digipeat control word          */
  650. #ifdef METERS
  651.     rxdev = DEFDEVMETER;    /* initialise rx dev meter control word      */
  652.     meterflags = DEFMETERFLAGS;
  653.     rxsigmin = DEFRXSIGMIN;
  654.     rxsmeter = DEFRXSMETER;
  655.     rxdb = DEFRXDB;
  656.     dbfloor = DEFDBFLOOR;
  657.     adcmult1 = DEFMULT1;
  658.     adcmult2 = DEFMULT2;
  659.     adcofs1 = DEFOFS1;
  660.     adcofs2 = DEFOFS2;
  661.     units1[0] = '\0';
  662.     units2[0] = '\0';
  663. #ifdef ALL_METERS
  664.     units3[0] = units4[0] = '\0';
  665.     adcmult3 = DEFMULT3;
  666.     adcmult4 = DEFMULT4;
  667.     adcofs3 = DEFOFS3;
  668.     adcofs4 = DEFOFS4;
  669. #endif    
  670. #endif
  671. #ifdef PK96
  672.     brate0 = DEFBRATE0;
  673.     brate1 = DEFBRATE1;
  674. #endif
  675. #ifdef PORTFLUSH
  676.     for( cnt = 0; cnt < NUMPORTS; cnt++ )
  677.         none_last_time[cnt] = flushed[cnt] = sentdata[cnt] = pending[cnt] = 0;
  678. #endif
  679.     }
  680. #ifdef MANAGED
  681.   auditmask = 0;
  682. #endif
  683. #ifdef PK96
  684.   set_brates();
  685. #endif
  686.   }
  687.  
  688. /*---------------------------------------------------------------------------*/
  689. VOID    timsrv()        /* zeitabhaengige Funktionen             */
  690.   {
  691.   char       *usnxtc;        /* naechstes Zeichen im Frame             */
  692.   char       *cmdnam;        /* Befehlsname                     */
  693.   unsigned zeit;        /* Zeit in 10ms seit letztem Service         */
  694.   unsigned usget;        /* Getcount                     */
  695.   register unsigned cnt;    /* Scratch Zaehler                 */
  696.   unsigned zeichen;        /* Scratch fuer gelesene Zeichen         */
  697.   register mhtyp *mhdp;        /* Pointer auf aktuelles Frame             */
  698.   mhtyp       *usrmhd;        /* User MBHD Kopie                 */
  699.   cmdtyp   *cmdpoi;        /* Pointer in Befehlstabelle             */
  700.   register mhtyp *bufpoi;       /* pointer for error message construction */
  701.   unsigned len;            /* length of help string current line */
  702.  
  703.   DIinc();            /* Interrupts aus                 */
  704.   zeit = tic10 - lastic;    /* vergangene Zeit seit letztem Service         */
  705.   lastic = tic10;        /* neuen Nullpunkt merken             */
  706.   decEI();            /* Interrupts wieder frei             */
  707.  
  708.   if (zeit != 0)        /* nicht zu oft...                 */
  709.     {
  710.       l2timr(zeit);        /* an Level2 melden                 */
  711.       if ((tic1s +=zeit) >= 100)    /* alle Sekunde:             */
  712.         {
  713.           tic1s -=100;        /* Uebertrag merken                 */
  714.           hostim();        /* Hostinterface                 */
  715.           chknoa();        /* Nichtstuer ueberwachen             */
  716.           brosrv();        /* Rundsprueche                     */
  717.           trasrv();        /* Level3 und Level4 Service             */
  718.           miscsrv();
  719.           beacon();        /* Bake                         */
  720.           arpsrv();
  721. #ifdef PK96
  722.           toggle_mail_led();
  723.           ASCI1ESC();
  724. #endif
  725.         }
  726.     }
  727.  
  728. #ifdef STATSCMD
  729.   if( ++cpu2load >= 100 )    /* bump counter 2 every loop,                */
  730.   {                /* and every 100 loops,                      */
  731.     cpu2load -= 100;        /* reset the counter                         */
  732.     cpuload++;            /* and bump the real counter, which thus     */
  733.   }                /* indicates loops divided by 100            */
  734. #endif
  735.  
  736. /*=== eingelaufene Info Frames fuer den CCP verarbeiten              ===*/
  737.   while ((mhdp = (mhtyp *) userhd.lnext) != (mhtyp *) &userhd.lnext)
  738.    {                                             /* Info Frames fuer CCP     */
  739.     unlink(mhdp);        /* Info aushaengen                 */
  740.  
  741.     for (userpo = (usrtyp *) usccpl.lnext;    /* User zur Info suchen         */
  742.         (usrtyp *) &usccpl != userpo;            /* gesamte Liste absuchen    */
  743.          userpo = userpo->unext) {
  744.       if ((mhdp->usrtyp == userpo->typ_u) /* Usertyp und Kontrollblock         */
  745.         && (mhdp->l2lnk == userpo->cblk_u)) /* muessen passen             */
  746.           break;        /* dann gefunden                 */
  747.       }
  748.  
  749.     if ((usrtyp *) &usccpl == userpo) {    /* kein User gefunden             */
  750. #ifdef MODIFIED
  751.       new_user();
  752. #else
  753.       userpo = (usrtyp *) allocb();    /* dann ist es ein neuer Teilnehmer  */
  754.       userpo->mbhd = 0;        /* keine Info wartend                 */
  755.       userpo->errcnt = 0;    /* bisher keine Fehler                 */
  756.       userpo->status = 1;    /* am CCP, Befehl kommt                 */
  757. #endif
  758.       userpo->sysflg = ! (userpo->typ_u = mhdp->usrtyp); /* Typ setzen         */
  759.       userpo->cblk_u = mhdp->l2lnk; /* Kontrollblock setzen             */
  760.       relink(userpo, usccpl.lprev); /* User in Kette haengen             */
  761. #ifdef TEXNET
  762.       if( userpo->typ_u == 2 ) 
  763.         userpo->cblk_u->realid[0] = -1 ;
  764. #endif
  765. #ifdef MODIFIED
  766.       if( cmpcal( alias, mhdp->l2lnk->srcid ) && *contxt != '\0' )
  767.           putmsg( contxt );
  768.       if( enaliases )
  769.       {
  770. #ifdef HOSTCMD
  771.         clicnt = 0;
  772.         if( cmpcal( bbsalias, mhdp->l2lnk->srcid ) )
  773.           ccpbbs();
  774.         else if( cmpcal( hostalias, mhdp->l2lnk->srcid ) )
  775.           ccphst();
  776. #ifdef DXCLUSTER
  777.         else if( cmpcal( dxcalias, mhdp->l2lnk->srcid ) )
  778.           ccpdxc();
  779. #endif
  780. #endif
  781.       }
  782. #endif
  783.       }
  784. /*=== eingelaufene Info Frames fuer User verarbeiten              ===*/
  785.     if (!(usrmhd = userpo->mbhd))
  786.       userpo->mbhd = mhdp;
  787.     else {
  788.       usnxtc = usrmhd->nxtchr;
  789.       usget = usrmhd->getcnt;
  790.       while (usrmhd->getcnt < usrmhd->putcnt)
  791.         getchr(usrmhd);
  792.       while (mhdp->getcnt < mhdp->putcnt)
  793.         putchr(getchr(mhdp), usrmhd);
  794.       usrmhd->nxtchr = usnxtc;
  795.       usrmhd->getcnt = usget;
  796.       dealmb(mhdp);
  797.       }
  798.     while ((userpo != 0)    /* existiert der User noch?             */
  799.       && ((mhdp = userpo->mbhd) != 0) /* ist Info da?                 */
  800.       && (getlin(mhdp) /* == 1*/ )) { /* ist es mindestens eine ganze Zeile? */
  801.        clipoi = clilin;        /* Zeile als leer definieren             */
  802.        clicnt = 0;
  803.       while ((mhdp->getcnt < mhdp->putcnt) /* so lange Zeichen vorhanden sind*/
  804.         && (((zeichen = getchr(mhdp)) & 0x7f) != 0x0d)) { /* und kein <CR>     */
  805. #ifdef MODIFIED
  806.         if( !( hlpflg & 0x20 ) || userpo->status != 4 )
  807. #endif
  808.           zeichen &= 0x7f;
  809.         if ((zeichen == 0x08) || (zeichen == 0x7f)) { /* Backspace         */
  810.           if (clicnt != 0) {    /* und Delete aussortieren             */
  811.             --clipoi;
  812.             --clicnt;
  813.             }
  814.           }
  815.         else {
  816.           if ((zeichen != 0x0a) /* Linefeed zaehlt nicht mit             */
  817.             && (clicnt < 80)) {    /* Zeilenueberlauf beachten             */
  818.             *clipoi++ = zeichen;/* Zeichen merken                 */
  819.             ++clicnt;        /* mitzaehlen                     */
  820.             }
  821.           }
  822.         }
  823.       if (mhdp->getcnt == mhdp->putcnt) { /* wenn nun alle Zeichen verbraucht*/
  824.         dealmb(mhdp);        /* Buffer wieder freigeben             */
  825.         userpo->mbhd = 0;    /* und "keine Info mehr da" markieren         */
  826.         }
  827.  
  828. /*=== Zeile vom User auswerten                          ===*/
  829.       clipoi = clilin;        /* zum Auswerten Pointer nach vorn         */
  830. #ifdef TEXNET
  831.       if( userpo->typ_u == 2 && userpo->cblk_u->realid[0] == -1 )
  832.       {
  833.         userpo->cblk_u->realid[0] = 0;
  834.         usnxtc = clipoi;
  835.         usget = clicnt;
  836.         if( (hlpflg & 0x80) && usrcmp( "*** LINKED to ", &clicnt, &clipoi ) )
  837.         {
  838.           if( getcal( &clicnt, &clipoi, 1, userpo->cblk_u->realid ) == 1 )
  839.           {
  840.             if( *contxt && ( hlpflg & 8 ) )
  841.               putmsg( contxt );
  842.           }
  843.           else
  844.             putmsg("Error - TexNet User ID invalid");
  845.           clicnt = 0;
  846.         }
  847.         else
  848.         {
  849.           clipoi = usnxtc;
  850.           clicnt = usget;
  851.         }
  852.       }
  853. #endif
  854.       if (userpo->status == 3  /* warten auf Passwort?             */
  855. #ifdef MANAGED
  856.          || userpo->status == 5 /* wait for passwd ? */
  857. #endif
  858. #ifdef CLOSEDOWN
  859.          || userpo->status == 7 /* waiting for closedown ?....... */
  860. #endif
  861.          )
  862.       {
  863. #ifdef MODIFIED
  864.       cnt = 0;            /* initialise counter to start value         */
  865.       while( clicnt > 0 )    /* step thru until eol or passwd found       */
  866.       {
  867.         if( *clipoi == ' ' ) { }    /* ignore spaces in the reply        */
  868.         else if( *clipoi == paswrd[userpo->paswrd[cnt] & 0xff] )
  869.         {            /* if the current char matches the passwd    */
  870.           if( cnt == 0 )    /* if this is the first char in the passwd   */
  871.           {
  872.             usnxtc = clipoi;    /* then save the current position to try     */
  873.             usget  = clicnt;    /* searching from if this one fails          */
  874.           }
  875.           if( ++cnt == 5 )    /* if a match is found for all 5 characters  */
  876.           {
  877.             clicnt = 0;        /* then scrap the rest of the line           */
  878.             break;        /* and exit from the loop                    */
  879.           }
  880.         }
  881.         else if( cnt > 0 )    /* if char does not match & we had a partial */
  882.         {
  883.           clipoi = usnxtc;    /* match then restart from the saved position*/
  884.           clicnt = usget;
  885.           cnt = 0;        /* and go back to scratch on the count       */
  886.         }
  887.         nxtcli();        /* step on one character and loop            */
  888.       }
  889. #else
  890.         for (cnt = 0; cnt < 5; ++cnt) { /* 5 Zeichen als Antwort         */
  891.           if (skipspace() == 0) /* noch was da?             */
  892.             break;        /* nein, dann Ende                 */
  893.           zeichen = *clipoi;    /* sonst Zeichen holen                 */
  894.           nxtcli();
  895.           if (paswrd[userpo->paswrd[cnt] & 0xff] != zeichen) /* stimmt?      */
  896.             break;
  897.           }
  898. #endif
  899.         if (cnt == 5)        /* 5 Richtige?                     */
  900.           userpo->sysflg = 1;
  901. #ifdef MANAGED
  902.         if( userpo->status == 5 && userpo->sysflg == 1 )
  903.           userpo->status = 6;                /* we made MANAGER ! */
  904.         else
  905. #endif
  906. #ifdef CLOSEDOWN
  907.         if( userpo->status == 7 && userpo->sysflg == 1 )
  908.           stop();                    /* do CLOSEDOWN !    */
  909.         else
  910. #endif
  911.         userpo->status = 1;    /* neuer Status: warten auf Befehl         */
  912.         }
  913. #ifdef TALKCMD
  914.       if( userpo->status == 4 )
  915.       {
  916.           if( clicnt >= 3 && *clipoi == '/' && upcase(*(clipoi+1)) == 'E'
  917.               && upcase(*(clipoi+2)) == 'X' )
  918.           {
  919.               userpo->status = 1;
  920.               notify( myid, 4, this_station(), NULL, "has left you.", 13 );
  921.               putmsg("Leaving talk.");
  922.           }
  923.           else
  924.               notify( this_station(), 4, NULL, NULL, clipoi, clicnt );
  925.       }
  926. #endif
  927.       else {
  928.  
  929.         if (userpo->status == 2) { /* warten auf Connect?             */
  930.           disusr(userpo->cblk_p, userpo->typ_p); /* dann beenden         */
  931.           userpo->status = 1;    /* neuer Status: warten auf Befehl         */
  932.           }
  933.  
  934.         if ( skipspace() && *clipoi != '#' ) { /*noch was in der Zeile?*/
  935.           usnxtc = clipoi;
  936.           usget = clicnt;    /* Position in der Zeile merken             */
  937. #ifdef MANAGED
  938.     if( ( auditmask & 0x20 ) && clicnt /* > 0 */ )
  939.         notify( L7id, 6, this_station(), NULL, clipoi, clicnt );
  940. #endif
  941. #ifdef MODIFIED
  942.           for (cnt=0, cmdpoi = cmdtab;    /* Eingabe mit Tabelle vergleichen   */
  943.                cmdpoi->cmdstr != 0;     /* Ende ist NULL             */
  944.                ++cmdpoi, cnt++)        /* also, bump cnt in the loop */
  945. #else
  946.           for (cmdpoi = cmdtab;    /* Eingabe mit Tabelle vergleichen         */
  947.                cmdpoi->cmdstr != 0; /* Ende ist NULL                 */
  948.                ++cmdpoi)
  949. #endif
  950.           {
  951.             clipoi = usnxtc;
  952.             clicnt = usget;    /* fuer jeden Test auf Zeilenanfang         */
  953.             cmdnam = cmdpoi->cmdstr;
  954.             while ((clicnt != 0) && (*clipoi != ' ')) {
  955.               if (upcase(*clipoi) != upcase(*cmdnam)) break; /* Abbruch bei ungleich */
  956.               nxtcli();
  957.               ++cmdnam;
  958.               }
  959.             if ((clicnt == 0) || (*clipoi == ' ')) break; /* passt das Wort? */
  960.             }
  961.           if (cmdpoi->cmdfun != 0) { /* auf Tabellenende gelaufen?         */
  962.             userpo->errcnt = 0;    /* nein, Fehlerzaehler ruecksetzen         */
  963.             skipspace(); /* vorruecken auf Argument         */
  964. #ifdef MODIFIED
  965.             /* implement the '+' and '-' command controls. If sysop, and if
  966.              * the first character following the command is '+' or '-', then
  967.              * set or clear the command control flag ( ie bit 0 ).
  968.              * Also, if the command is disabled, use cnt to apologise
  969.              * The bit affected is the display or enable bit ( 'D' )
  970.             */
  971.             if( issyso() && ( *clipoi == '-' || *clipoi == '+' ) )
  972.             {
  973.                 zeichen = ( *clipoi == '-' );
  974.                 nxtcli();
  975.                 if( skipspace() && upcase( *clipoi ) == 'D' )
  976.                     len = 2;
  977.                 else
  978.                     len = 1;
  979.                 if( zeichen )
  980.                     defcsr[cnt] |= len;
  981.                 else
  982.                     defcsr[cnt] &= ~len;
  983.             }
  984.             else if( ( defcsr[cnt] & 1 )
  985. #ifdef ACL
  986. #ifdef ACL_DISCMD_OVERRIDE
  987.                      && ((acl_entry( this_station() ) & ACL_DIS_OVERRIDE )==0)
  988. #endif
  989. #endif
  990.                    ) 
  991.  
  992.             {
  993.                 bufpoi = putals("Sorry, '");
  994.                 putstr( cmdpoi->cmdstr, bufpoi );
  995.                 putstr( "' is not enabled.", bufpoi );
  996.                 seteom( bufpoi );
  997.             }
  998.             else
  999. #endif
  1000.             (*cmdpoi->cmdfun)(); /* Befehl ausfuehren                 */
  1001.             }
  1002.           else {
  1003. #ifdef MODIFIED
  1004.             /* print a more helpful error message that shows the commands
  1005.              * that can be used. If the control byte is zero, show it.
  1006.              * This means that sysop commands are never shown
  1007.              */
  1008.             bufpoi = putals("Invalid Command - Choose from :\015");
  1009.             len = bufpoi->putcnt;
  1010.             for (cnt=0, cmdpoi = cmdtab;    /* Eingabe mit Tabelle vergleichen         */
  1011.                cmdpoi->cmdstr != 0; /* Ende ist NULL                 */
  1012.                ++cmdpoi, cnt++)
  1013.             {
  1014.                 if(((defcsr[cnt] & 3)==0) || (userpo->sysflg && (hlpflg & 2)))
  1015.                 {
  1016.                     if( bufpoi->putcnt - len > 70 )    /* line len exceeded?*/
  1017.                     {                    /* if so, do cr-lf   */
  1018.                         putchr('\015', bufpoi );
  1019.                         len = bufpoi->putcnt;
  1020.                     }
  1021.                     putstr( cmdpoi->cmdstr, bufpoi);
  1022.                     putchr( ' ', bufpoi );
  1023.                 }
  1024.             }
  1025.             seteom( bufpoi );
  1026. #else
  1027.             putmsg("Invalid Command (CONNECT CQ INFO NODES ROUTES USERS)");
  1028. #endif
  1029.  
  1030.             if (++userpo->errcnt == 5)  /* Fehler zaehlen             */
  1031. #ifdef MODIFIED
  1032.                /* call the bye command rather than just throwing him off
  1033.                */
  1034.                ccpbye();
  1035. #else
  1036.             {
  1037.               disusr(userpo->cblk_u, userpo->typ_u);
  1038.               kilusr();        /* zuviel Mist? Rauswerfen             */
  1039.             }
  1040. #endif
  1041.   } } } } } 
  1042. #ifdef MANAGED
  1043.   userpo = NULL;
  1044. #endif
  1045. }
  1046.  
  1047. /*---------------------------------------------------------------------------*/
  1048. VOID    l2tol7(opcod, link, type)/* auf S-Frame reagieren             */
  1049. unsigned opcod;            /* Frametyp: 1=UA, 2=DISC, 3=DM, 4=?         */
  1050. ctyp     *link;            /* Kontrollblock                 */
  1051. unsigned type;        /* User Typ                     */
  1052.   {
  1053.   register unsigned cnt;    /* Scratch Zaehler                 */
  1054.   register ptctyp *patchp;
  1055.   register unsigned typ = type;        /* User Typ                     */
  1056.  
  1057.   if (opcod < 5) {        /* zulaessiger Frametyp?             */
  1058.  
  1059.     if (opcod == 1) {        /* UA Frame                     */
  1060.       for (userpo = (usrtyp *) usccpl.lnext;    /* User in CCP-Liste suchen  */
  1061.            (usrtyp *) &usccpl != userpo;
  1062.            userpo = userpo->unext) {
  1063.         if ((userpo->status == 2) /* Status des Users: "SABM gegeben"?         */
  1064.           && (userpo->typ_p == typ) /* Partner muss erwarteter Typ sein         */
  1065.           && (userpo->cblk_p == (l2ltyp *) link)){ /* Kontrollblock passt?   */
  1066.           msgfrm('D', link, typ, conmsg); /* Erfolg melden             */
  1067.           for (patchp = ptcrdl;    /* Platz in Patchcordliste suchen         */
  1068.                patchp->luserl != 0;
  1069.                patchp += 2);
  1070.           patchp->luserl = userpo->cblk_u; /* beide User eintragen         */
  1071.           patchp->lusert = userpo->typ_u;  /* Kontrollblock und Typ         */
  1072.           (++patchp)->luserl = (l2ltyp *) link;
  1073.           patchp->lusert = typ;
  1074.           kilusr();        /* User aus Level7 entfernen             */
  1075.           break;
  1076.           }
  1077.         }
  1078.       return;            /* fertig                     */
  1079.       }
  1080.     for (cnt = 0, patchp = ptcrdl; /* DISC oder DM erhalten             */
  1081.          cnt < NUMPAT;        /* Patchcordliste nach User absuchen         */
  1082.          ++cnt, ++patchp)
  1083.      {
  1084.       if ((patchp->lusert == typ)
  1085.         && (patchp->luserl == (l2ltyp *) link))
  1086.        {
  1087.         patchp->luserl = 0;    /* Eintrag loeschen                 */
  1088.         cnt ^= 1;           /* auf andere Seite der Verbindung         */
  1089.         patchp = &ptcrdl[cnt];
  1090. #ifdef MODIFIED
  1091.     if( (cnt & 1) == 0 && reconnect )
  1092.     {
  1093.             new_user();
  1094.             userpo->status = 0;
  1095.             userpo->cblk_u = (l2ltyp *)patchp->luserl;
  1096.             userpo->typ_u = patchp->lusert;
  1097.             relink( userpo, usccpl.lnext );
  1098.             putmsg( "Welcome back.");
  1099.         }
  1100.         else
  1101. #endif
  1102.             disusr(patchp->luserl, patchp->lusert);    /* Partner         */
  1103.         patchp->luserl = 0;            /* Eintrag loeschen         */
  1104.         return;                    /* fertig             */
  1105.        }
  1106.      }
  1107.     for (userpo = (usrtyp *) usccpl.lnext;    /* muss CCP User sein         */
  1108.          (usrtyp *) &usccpl != userpo;    /* Tabelle absuchen             */
  1109.          userpo = userpo->unext) {
  1110.       if ((userpo->typ_u == typ)
  1111.         && (userpo->cblk_u == (l2ltyp *) link)) {
  1112.         if (userpo->status == 2) /* User hat Connect gefordert?             */
  1113.           disusr(userpo->cblk_p, userpo->typ_p); /* Partner abwerfen         */
  1114.         kilusr();        /* und User selbst abwerfen             */
  1115.         return;            /* fertig                     */
  1116.         }
  1117.       if (userpo->status == 2) { /* User hat Connect gefordert             */
  1118.         if ((userpo->typ_p == typ) /* und Antwort kam vom Partner         */
  1119.         && (userpo->cblk_p == (l2ltyp *) link)) {
  1120.           msgfrm('D', link, typ, ((opcod == 3)? dmmsg : "Failure with "));
  1121.           userpo->status = 1;    /* neuer Status ist "warten auf Befehl"         */
  1122.           return;
  1123.         } }
  1124.       }
  1125.     }
  1126.   }
  1127.  
  1128. /*---------------------------------------------------------------------------*/
  1129. VOID    disusr(link, typ)    /* User abwerfen                 */
  1130. ctyp     *link;            /* Kontrollblock                 */
  1131. unsigned typ;            /* User Typ                     */
  1132.   {
  1133.   register l2ltyp *cblk2;    /* Kopien der Kontrollblockpointer         */
  1134.   register cirtyp *cblk4;
  1135.   register hustyp *cblk0;
  1136.  
  1137.   switch(typ)
  1138.    {
  1139.     case 4:            /* Circuit?                     */
  1140.      cblk4 = cirpoi;
  1141.      cirpoi = (cirtyp *) link;
  1142.      discir();
  1143.      cirpoi = cblk4;
  1144.      break;
  1145.  
  1146.     case 2:            /* Level2?                     */
  1147.      cblk2 = lnkpoi;
  1148.      lnkpoi = (l2ltyp *) link;
  1149.      dsclnk();
  1150.      lnkpoi = cblk2;
  1151.      break;
  1152.  
  1153.  
  1154.     default:            /* Host                         */
  1155.      cblk0 = hstusr;
  1156.      hstusr = (hustyp *) link;
  1157.      hstout();
  1158.      hstusr = cblk0;
  1159.    }
  1160.   }
  1161.  
  1162. /*---------------------------------------------------------------------------*/
  1163. BOOLEAN    fmlink(conflg, bufpoi)    /* Frame an User weiterreichen             */
  1164. register mhtyp    *bufpoi;    /* Info                         */
  1165. register BOOLEAN conflg;    /* Congestion Flag                 */
  1166.   {
  1167.   register unsigned cnt;    /* Scratch Zaehler                 */
  1168.  
  1169.   for (cnt = 0, ptcrdp = ptcrdl; /* Patchcordliste absuchen             */
  1170.        cnt < NUMPAT;        /* ob User connected ist zu Partner         */
  1171.        ++cnt, ++ptcrdp)
  1172.    {
  1173.     if ((bufpoi->usrtyp == ptcrdp->lusert) /* Usertyp                 */
  1174.      && (bufpoi->l2lnk == ptcrdp->luserl)) /* und Kontrollblock gleich?         */
  1175.      {
  1176.       cnt ^= 1;           /* auf andere Seite der Verbindung         */
  1177.       ptcrdp = &ptcrdl[cnt];
  1178.       bufpoi->l2lnk = ptcrdp->luserl; /* Kontrollblock des Pratners eintragen*/
  1179.       switch (ptcrdp->lusert)
  1180.        {
  1181.         case 4:                    /* User ist Circuit?         */
  1182.         return(itocir(conflg, bufpoi));
  1183.  
  1184.         case 2:                    /* User ist Level2?         */
  1185.         return(itolnk(conflg, bufpoi));
  1186.  
  1187.         default:
  1188.         return(hstrec(conflg, bufpoi));        /* User ist Host         */
  1189.        }
  1190.       }
  1191.     }
  1192.   relink(unlink(bufpoi), userhd.lprev);        /* User ist im CCP         */
  1193.   return(TRUE);
  1194.   }
  1195.  
  1196. /*---------------------------------------------------------------------------*/
  1197. VOID    seteom(bufpoi)        /* Ende Kennung an Frame anhaengen         */
  1198. register mhtyp    *bufpoi;
  1199.   {
  1200.   mhtyp    mbhd;
  1201.  
  1202.   putchr('\015', bufpoi);        /* Zeilenende                 */
  1203.   rwndmb(bufpoi);            /* alle Pointer auf Null         */
  1204.   inithd(&mbhd);
  1205.   relink(bufpoi, &mbhd);
  1206.   switch (bufpoi->usrtyp)
  1207.    {
  1208.     case 4:                /* User ist Circuit             */
  1209.      itocir(1, bufpoi);
  1210.      break;
  1211.  
  1212.     case 2:                /* User ist Level2             */
  1213.      itolnk(1, bufpoi);
  1214.      break;
  1215.  
  1216.     default:                /* User ist Host             */
  1217.      hstrec(1, bufpoi);
  1218.  
  1219.    }
  1220.   }
  1221.  
  1222. /*---------------------------------------------------------------------------*/
  1223. VOID    beacon()        /* Bakenservice                     */
  1224.   {
  1225.   register unsigned kanal;        /* Kanal fuer Sendung             */
  1226.   register mhtyp *bufpoi;        /* Buffer fuer Frame             */
  1227.  
  1228.   if ((beacen != 0) && (nmbfre > 128)) { /* Bake frei und Platz?         */
  1229. #ifdef MODIFIED
  1230.     if (++beatim >= beaint) {    /* alle beaint min                 */
  1231. #else
  1232.     if (++beatim >= 600) {    /* alle 10 min                     */
  1233. #endif
  1234.       beatim = 0;
  1235.       (bufpoi = (mhtyp *) allocb())->pid = PID_NO_L3; /* Buffer beschaffen   */
  1236.       putstr(version, bufpoi); /* Meldung in Buffer             */
  1237.       if (alias[0] != ' ') {    /* Ident definiert?                 */
  1238.         putstr(" (", bufpoi);
  1239.         putcal(alias, bufpoi);    /* dann Ident auch in Buffer             */
  1240.         putstr(") ", bufpoi);
  1241. #ifdef MODIFIED
  1242.         if( *beatxt != '\0' )        /* if we have additional beacon text */
  1243.           putstr( beatxt, bufpoi );    /* then add it to the message        */
  1244. #endif
  1245.         }
  1246.       putchr('\015', bufpoi);    /* Frame schliessen                 */
  1247.  
  1248.       for (kanal = 0; kanal < NUMPORTS; ++kanal) /* auf beide Kanaele geben  */
  1249.        {
  1250.         if ((beacen == 2) || (istraf[kanal] == 1))
  1251.          {
  1252.           rwndmb(bufpoi);        /* alle Pointer auf Null         */
  1253.           sdui(beadil, beades, myid, kanal, bufpoi); /* als UI senden         */
  1254.           istraf[kanal] = 0;        /* Bake fuer diesen Kanal erledigt   */
  1255.          }
  1256.        }
  1257.       dealmb(bufpoi);        /* Buffer wieder freigeben             */
  1258.       }
  1259.     }
  1260.   }
  1261.  
  1262. /*---------------------------------------------------------------------------*/
  1263. #ifdef MODIFIED
  1264.  
  1265. /* common code to command interpreter and l2tol7() that creates a
  1266.  * structure for the user session.
  1267.  */
  1268. VOID new_user()
  1269. {
  1270.     userpo = (usrtyp *)allocb();
  1271.     userpo->mbhd = 
  1272.     userpo->errcnt = 0;
  1273.     userpo->status = 1;
  1274. }
  1275. #endif
  1276.  
  1277. /*---------------------------------------------------------------------------*/
  1278. #ifdef TEXNET
  1279. usrcmp( match, length, string )
  1280. register char *match;
  1281. register char * *string;
  1282. register unsigned *length;
  1283. {
  1284.     while( *match == *(*string) && *match && *length )
  1285.     {
  1286.         ++*string;
  1287.         --*length;
  1288.         ++match;
  1289.     }
  1290.     return( *match == '\0' );
  1291. }
  1292.  
  1293. #endif
  1294.  
  1295.  
  1296. /*--- Ende Level 7a ---------------------------------------------------------*/
  1297.